home *** CD-ROM | disk | FTP | other *** search
- /*
- Blob Manager Demonstration: Tic-Tac-Toe
-
- 25 July 1986 Paul DuBois
- */
-
- # include "BlobDemo.h"
- # include <ControlMgr.h>
-
-
- # define barWidth 3 /* board line size */
- # define bSqSize 30 /* board square size */
- # define pSqSize 28 /* playing piece square size */
- # define yOffMesg 4
- # define yOffPiece 24 /* offset of top of pieces */
- # define xOffBoard 25
- # define yOffBoard 59
- # define xMid 73 /* xOffBoard + 1.5(bSqSize) + barWidth */
- # define yOffBut 165
-
-
- static GrafPtr tttPort;
- static BlobSetHandle tttReceptors; /* receptor blobs (board) */
- static BlobSetHandle tttDonors; /* donor blobs (pieces) */
- static BlobHandle xBlob; /* handles to each piece */
- static BlobHandle oBlob;
-
- static Boolean haveWin;
- static Boolean wait = false;
- static ControlHandle restartCtl;
- static int moves;
- static int firstPlayer = 0;
- static Str255 statusStr;
-
-
- TttStatusMesg (s)
- Str255 s;
- {
- Rect r;
-
- SetRect (&r, xMid-40, yOffMesg, xMid+40, yOffMesg+20);
- TextBox (s+1, (long) s[0], &r, 1);
- StrCpy (statusStr, s);
- }
-
-
- TttGameOver (mesg)
- Str255 mesg;
- {
- HiliteControl (restartCtl, 0);
- TttStatusMesg (mesg);
- wait = true;
- }
-
-
-
- TttSelectPlayer ()
- {
- BlobHandle b;
- int i;
-
- i = (moves + firstPlayer) % 2; /* 0 = X, 1 = O */
- HiliteBlob (GetBlobHandle (tttDonors, i), inFullBlob, normalDraw);
- HiliteBlob (GetBlobHandle (tttDonors, 1 - i), inFullBlob, dimDraw);
- if (i)
- TttStatusMesg ("\pO's Move");
- else
- TttStatusMesg ("\pX's Move");
- /*
- Freeze board except for positions occupied by current player and
- empty positions.
- This allows pieces to be played either by playing the piece at
- the top, or by duplicating them on the board. (Can't drag onto
- another of own pieces, since replace transactions are disallowed.)
- */
- ThawBlobSet (tttReceptors);
- for (b = FirstBlob (tttReceptors); b != nil; b = NextBlob (b))
- {
- if (BGlob (b) != nil && BGlob (b) != GetBlobHandle (tttDonors, i))
- FreezeBlob (b);
- }
- }
-
-
- TttRestart ()
- {
- HiliteControl (restartCtl, 255);
- ZUnglueGlobSet (tttReceptors);
- HiliteBlobSet (tttReceptors, inFullBlob, normalDraw);
- moves = 0;
- TttSelectPlayer ();
- wait = false;
- }
-
-
- /*
- Dim the board positions that are not part of the win. Dim them all
- on "cat's game."
- */
-
- TttShowWinner (pos)
- int pos;
- {
- int i;
- BlobHandle b;
-
- for (i = 0; i < 9; ++i)
- {
- b = GetBlobHandle (tttReceptors, i);
- if ((pos % 2) == 0) /* this pos not part of win */
- HiliteBlob (b, inFullBlob, dimDraw); /* so dim it */
- pos >>= 1;
- }
- }
-
- TttTestConfig (pos, testPos)
- int pos, testPos;
- {
- int i;
- BlobHandle b;
-
- if ((pos & testPos) == testPos) /* have a win */
- {
- haveWin = true;
- TttShowWinner (testPos);
- }
- }
-
-
- TttTestWin (b, boardPos)
- BlobHandle b;
- int boardPos;
- {
- if (!haveWin) /* don't bother if other player already won */
- {
- TttTestConfig (boardPos, 0x007); /* top row */
- TttTestConfig (boardPos, 0x038); /* middle row */
- TttTestConfig (boardPos, 0x1c0); /* bottom row */
- TttTestConfig (boardPos, 0x049); /* left column */
- TttTestConfig (boardPos, 0x092); /* middle column */
- TttTestConfig (boardPos, 0x124); /* right column */
- TttTestConfig (boardPos, 0x111); /* diagonal */
- TttTestConfig (boardPos, 0x054); /* diagonal */
- if (haveWin)
- {
- if (b == xBlob)
- {
- TttGameOver ("\pX Wins"); /* loser goes first next time */
- firstPlayer = 1;
- }
- else
- {
- TttGameOver ("\pO Wins");
- firstPlayer = 0;
- }
- }
- }
- }
-
-
- TttBoardPos (b)
- BlobHandle b;
- {
- int i, mask, result;
- BlobHandle b2;
-
- result = 0;
- mask = 1;
- for (i = 0; i < 9; ++i)
- {
- b2 = GetBlobHandle (tttReceptors, i);
- if ((**b2).glob == b) /* board occupied by desired piece */
- result |= mask;
- mask <<= 1;
- }
- return (result);
- }
-
-
- TttCheckStatus ()
- {
- int xbPos, obPos;
-
- haveWin = false;
- xbPos = TttBoardPos (xBlob);
- obPos = TttBoardPos (oBlob);
- TttTestWin (xBlob, xbPos);
- TttTestWin (oBlob, obPos);
- if (!haveWin) /* no win, but board might be full now */
- {
- if ((xbPos | obPos) == 0x1ff)
- {
- TttShowWinner (0);
- TttGameOver ("\pCat's Game");
- firstPlayer = 1 - firstPlayer; /* alternate on a draw */
- }
- }
- }
-
-
- TttMouse (pt, t, mods)
- Point pt;
- long t;
- int mods;
- {
- int result;
- ControlHandle ctl;
-
- if (FindControl (pt, tttPort, &ctl))
- {
- if (TrackControl (ctl, pt, nil))
- {
- TttRestart ();
- }
- }
- else if (!wait)
- {
- BlobClick (pt, t, tttDonors, tttReceptors);
- result = BClickResult ();
- if (result == bcGlue || result == bcDup)
- {
- ++moves;
- TttCheckStatus ();
- if (!wait) /* no win yet */
- {
- TttSelectPlayer ();
- }
- }
- }
- }
-
- TttUpdate (resized)
- Boolean resized;
- {
- DrawControls (tttPort);
- TttStatusMesg (statusStr);
- DrawGrid (3, 3, xOffBoard, yOffBoard, bSqSize, bSqSize, barWidth, barWidth);
- DrawBlobSet (tttDonors);
- DrawBlobSet (tttReceptors);
- }
-
-
- TttActivate (active)
- Boolean active;
- {
- if (active)
- {
- SetDragRects (tttPort);
- SetBCPermissions (false, false, true, false, false);
- }
- }
-
-
- /*
- Make receptor blobs
- */
-
- TttMakeRBlob (r)
- Rect *r;
- {
- BlobHandle b;
-
- b = NewBlob (tttReceptors, false, 0, false, 0L);
- OpenBlob ();
- EraseRect (r);
- InsetRect (r, 1, 1);
- FrameRect (r);
- InsetRect (r, 2, 2);
- FrameRect (r);
- InsetRect (r, -2, -2);
- CloseRectBlob (b, r, r);
- }
-
-
- TttMakeReceptors ()
- {
- tttReceptors = NewBlobSet ();
- MakeBlobGrid (3, 3, xOffBoard, yOffBoard, bSqSize, bSqSize,
- barWidth, barWidth, &TttMakeRBlob);
- }
-
-
- /*
- Make donor blobs
- */
-
- TttMakeDBlob (b, ch, x, y)
- BlobHandle *b;
- int ch, x, y;
- {
- Rect r;
-
- *b = NewBlob (tttDonors, false, 9, false, 0L);
- OpenBlob ();
- SetRect (&r, 0, 0, pSqSize, pSqSize);
- OffsetRect (&r, x, y);
- EraseRect (&r);
- PenSize (2, 2);
- FrameRect (&r);
- PenNormal ();
- MoveTo (r.left+pSqSize/2-4, r.bottom-pSqSize/2+5);
- DrawChar ((char) ch);
- CloseRectBlob (*b, &r, &r);
- }
-
-
- TttMakeDonors ()
- {
- tttDonors = NewBlobSet ();
- TttMakeDBlob (&xBlob, 'X', xMid-pSqSize-5, yOffPiece);
- TttMakeDBlob (&oBlob, 'O', xMid+5, yOffPiece);
- }
-
-
- TttInit ()
- {
- Rect r;
-
- tttPort = GetDemoWind (tttWindRes);
- SkelWindow (tttPort,
- TttMouse, /* mouse clicks */
- nil, /* key clicks */
- TttUpdate, /* updates */
- TttActivate, /* activate/deactivate events */
- nil, /* close window */
- DoWClobber, /* dispose of window */
- nil, /* idle proc */
- false); /* irrelevant, since no idle proc */
-
- TttMakeReceptors ();
- TttMakeDonors ();
- EnableBlobSet (tttReceptors);
- EnableBlobSet (tttDonors);
- SetRect (&r, xMid-45, yOffBut, xMid+45, yOffBut+20);
- restartCtl = NewControl (tttPort, &r, "\pRestart", true, 0, 0, 0,
- pushButProc, nil);
- TttRestart ();
- TttUpdate ();
- ValidRect (&tttPort->portRect);
- }
-